package com.yc.mybatis.core;

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;


import com.mysql.cj.util.StringUtils;
import com.yc.mybatis.core.MapperInfo;
import com.yc.mybatis.core.StringUtil;

public class SqlSessionFactory {
	private InputStream is = null;//配置文件
	//存放数据库连接信息
	private Map<String,String>  dataSourceMap = new Hashtable<String,String>();
	private List<String> mappers = new Vector<String>();//存放映射文件路径
	private Map<String,MapperInfo> mapperInfos = new Hashtable<String,MapperInfo>();
	private ConnectionPool connectionPool =null;
	int n=0;
	
	public SqlSession openSession() {
		return new SqlSession(connectionPool,mapperInfos);
	}
	
	public SqlSessionFactory(InputStream is) {
		this.is =is;
		init();
	}
	
	public SqlSessionFactory() {
		System.out.println("SqlSessionFactory");
		this.is =is;
		init();
	}

	private void init() {
		parseConfigXml();// 解析config.xml文件
		
		parseMapperXml();
//		dataSourceMap.forEach((key,val)->{
//		System.out.println("data =="+key+ ":"+val);
//		});
		
//		mappers.forEach(System.out::println);
//		
//		mapperInfos.forEach((key,val)->{
//		System.out.println("mapper =="+key+ ":"+val);
//	});
		
		ConnectionPoolFactory.create(dataSourceMap.get("driver"),dataSourceMap.get("url"),
				dataSourceMap.get("username"),dataSourceMap.get("password"));
		connectionPool = ConnectionPoolFactory.getInstance();
	}
/**
 * 解析映射文件
 */
	private void parseMapperXml() {
		if(mappers == null || mappers.isEmpty()) {
			return;
		}
		
		SAXReader reader = null;
		MapperInfo mapperInfo = null;
		Document doc = null;
		XPath xpath = null;
		
		String basePath = "";
		String nodeName = null;
		String sql = null;
		List<Node> nodes =null;
		Element el = null;
		
		Pattern pattern = null;
		Matcher matcher = null;
		
		List<String > params = null;
		for(String mapper : mappers) {
			try(InputStream iss = this.getClass().getClassLoader().getResourceAsStream(mapper)){
				if(iss == null) {
					throw new RuntimeException("映射文件"+ mapper + " 读取失败。。。。。");
				}
				
				reader = new SAXReader();
				doc = reader.read(iss);
				
				basePath = doc.getRootElement().attributeValue("namespace"); //获取根节点中的命名空间的值
				if(!StringUtil.checkNull(basePath)) {
					basePath +=".";
				}
				
				xpath = doc.createXPath("/mapper/*");
				nodes = xpath.selectNodes(doc);
				if(nodes == null || nodes.isEmpty()) {
					continue;// 读取下一个文件
				}
				
				for(Node node : nodes) {
					nodeName = node.getName().toLowerCase();
//					System.out.println(nodeName);
					if(!"update".equals(nodeName) && !"insert".equals(nodeName) && !"delete".equals(nodeName) && !"select".equals(nodeName)) {
						continue;
					}
					mapperInfo = new MapperInfo();
					if("select".equals(nodeName)) {
						mapperInfo.setUpdate(false);
					}
					
					el = (Element) node;
					mapperInfo.setResultType(el.attributeValue("resultType"));
					mapperInfo.setParameterType(el.attributeValue("parameterType"));
					sql = el.getTextTrim();
//					System.out.println(sql);
					
					pattern = Pattern.compile("[#][{]\\w+}");
					matcher =pattern.matcher(sql);
					params = new Vector<String>();
					while(matcher.find()) {
						params.add(matcher.group().replaceAll("[#{}]*",""));
					}
					sql = matcher.replaceAll("?");
					mapperInfo.setSql(sql);
					mapperInfo.setParams(params);
					mapperInfos.put(basePath+ el.attributeValue("id"),mapperInfo);
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (DocumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
/**
 * 解析配置文件
 */
	private void parseConfigXml() {
		SAXReader reader = new SAXReader();
		if(is == null) {
			throw new RuntimeException("读取配置文件夹失败");
		}
		
		try {
			Document doc = reader.read(is);
			
			XPath xpath = doc.createXPath("//dataSource/property");
			List<Node> properties =xpath.selectNodes(doc);
			if(properties == null || properties.isEmpty()) {
				throw new RuntimeException("读取数据库连接信息失败........");
			}
			
			Element el;
			for(Node node : properties) {
				el = (Element) node;
				dataSourceMap.put(el.attributeValue("name"), el.attributeValue("value"));
				
			}
			xpath = doc.createXPath("//mappers/mapper");
			List<Node> listMappers = xpath.selectNodes(doc);
			
			if(listMappers == null || listMappers.isEmpty()) {
				return;
			}
			
			for(Node node : listMappers) {
				el = (Element) node;
				mappers.add(el.attributeValue("resource"));
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}
